﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using JXT.PrimaryKey.Batman.Reflection;
using JXT.PrimaryKey.Batman.Domain.Models;

namespace JXT.PrimaryKey.Batman.Domain.Repositories.MySql.Expressions
{
    public class UpdateQuery : ISqlQuery {
        protected StringBuilder sb = new StringBuilder();
        protected IList<IDataParameter> paramaterList = new List<IDataParameter>();

        private string _keyId = "id";

        public UpdateQuery()
        {
        }

        public UpdateQuery(string keyId)
        {
            _keyId = keyId;
        }

        private string getTableName(Type type)
        {
            return type.Name.ToLower();
        }

        #region ISqlQuery Members

        public string QueryText {
            get { return sb.ToString(); }
        }

        public IDataParameter[] Parameters {
            get { return paramaterList.ToArray(); }
        }

        #endregion

        public void Append<TEntity>(TEntity entity) {
            if (entity == null)
                throw new ArgumentNullException("entity");
            string tableName = getTableName(entity.GetType());
            sb.AppendFormat("update {0}{1}{2} set ",
                DbEnviroumentFactory.Instanse.LeftTag,
                tableName,
                DbEnviroumentFactory.Instanse.RightTag);
            var dics = entity.GetType().GetMetadataCacheDictionary();
            int len = sb.Length;
            foreach (var item in dics) {
                if (item.Value.Property.Property.PropertyType.IsEntityOrValueObjectType()
                    || item.Value.Property.Property.PropertyType.IsInterface)
                    continue;
                string columnName = item.Value.Property.Name.ToLower();
                if (!columnName.Equals(_keyId, StringComparison.InvariantCultureIgnoreCase)) {
                    sb.AppendFormat("{0}{1}{2} {3} {4}{1}, ",
                        DbEnviroumentFactory.Instanse.LeftTag,
                        columnName,
                        DbEnviroumentFactory.Instanse.RightTag,
                        DbEnviroumentFactory.Instanse.EqualTag,
                        DbEnviroumentFactory.Instanse.ParameterChar);
                    paramaterList.Add(ParameterFactory.Create(
                        String.Format("{0}{1}",
                            DbEnviroumentFactory.Instanse.ParameterChar,
                            columnName),
                        item.Value.Property.Get(entity)));
                }
            }
            if (sb.Length != len) {
                sb.Remove(sb.Length - 2, 2);
            }
            var find = dics.First(e => e.Key.Equals(_keyId, StringComparison.InvariantCultureIgnoreCase));
            sb.AppendFormat(" where {0}{1}{2} {3} {4}{1}",
                DbEnviroumentFactory.Instanse.LeftTag,
                find.Key,
                DbEnviroumentFactory.Instanse.RightTag,
                DbEnviroumentFactory.Instanse.EqualTag,
                DbEnviroumentFactory.Instanse.ParameterChar);
            paramaterList.Add(ParameterFactory.Create(
                String.Format("{0}{1}",
                    DbEnviroumentFactory.Instanse.ParameterChar,
                    find.Key),
                find.Value.Property.Get(entity)));
        }
    }
}
